﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Cofe.Core.Utils
{
#if NETFX_CORE

    /// <summary>
    /// This doesnt work!
    /// </summary>
    public enum BindingFlags
    {
        Default = 0,
        IgnoreCase = 1,
        DeclaredOnly = 2,
        Instance = 4,
        Static = 8,
        Public = 16,
        NonPublic = 32,
        FlattenHierarchy = 64,
        InvokeMethod = 256,
        CreateInstance = 512,
        GetField = 1024,
        SetField = 2048,
        GetProperty = 4096,
        SetProperty = 8192,
        PutDispProperty = 16384,
        PutRefDispProperty = 32768,
        ExactBinding = 65536,
        SuppressChangeType = 131072,
        OptionalParamBinding = 262144,
        IgnoreReturn = 16777216,
    }

    public static class WinRT_Utils
    {
        /// <summary>
        /// https://gist.github.com/3520487
        /// </summary>
        /// <param name="type"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static IEnumerable<MethodInfo> GetMethods(this Type type, string name)
        {
            return GetMethods(type.GetTypeInfo(), name);
        }

        public static IEnumerable<MethodInfo> GetMethods(this TypeInfo typeInfo, string name)
        {
            TypeInfo currentTypeInfo = typeInfo;
            do
            {
                foreach (MethodInfo methodInfo in currentTypeInfo.GetDeclaredMethods(name))
                {
                    yield return methodInfo;
                }
                currentTypeInfo = typeInfo.BaseType.GetTypeInfo();
            } while (currentTypeInfo != null && currentTypeInfo.Name != "Object");
        }

        public static MethodInfo GetMethod(this Type type, string name)
        {
            return GetMethods(type.GetTypeInfo(), name).First();
        }

        public static MethodInfo GetMethod(this TypeInfo type, string name)
        {
            return GetMethods(type, name).First();
        }


        public static IEnumerable<MethodInfo> GetMethods(this Type type)
        {
            return type.GetRuntimeMethods();
        }

        public static IEnumerable<FieldInfo> GetFields(this Type type)
        {
            return type.GetRuntimeFields();
        }


        //https://gist.github.com/2464327/download#

        public static PropertyInfo GetProperty(this Type type, String propertyName)
        {
            return type.GetTypeInfo().GetDeclaredProperty(propertyName);
        }

        //public static MethodInfo GetMethod(this Type type, String methodName)
        //{
        //    return type.GetTypeInfo().GetDeclaredMethod(methodName);
        //}

        public static bool IsSubclassOf(this Type type, Type parentType)
        {
            return type.GetTypeInfo().IsSubclassOf(parentType);
        }

        //public static bool IsAssignableFrom(this Type type, Type parentType)
        //{
        //    return type.GetTypeInfo().IsAssignableFrom(parentType.GetTypeInfo());
        //}

        public static bool IsEnum(this Type type)
        {
            return type.GetTypeInfo().IsEnum;
        }

        public static bool IsPrimitive(this Type type)
        {
            return type.GetTypeInfo().IsPrimitive;
        }

        public static Type GetBaseType(this Type type)
        {
            return type.GetTypeInfo().BaseType;
        }

        public static bool IsGenericType(this Type type)
        {
            return type.GetTypeInfo().IsGenericType;
        }

        public static Type[] GetGenericArguments(this Type type)
        {
            return type.GetTypeInfo().GenericTypeArguments;
        }

        public static object GetPropertyValue(this Object instance, string propertyValue)
        {
            return instance.GetType().GetTypeInfo().GetDeclaredProperty(propertyValue).GetValue(instance);
        }

        public static TypeInfo GetTypeInfo(this Type type)
        {
            IReflectableType reflectableType = (IReflectableType)type;
            return reflectableType.GetTypeInfo();
        }

    }

#else 
    public static class WinRT_Utils
    {
      public static bool IsGenericType(this Type type)
        {
            return type.IsGenericType;
        }
    }
#endif
}
